﻿using Abide_AddOn_API.Interfaces;
using Abide_Halo_Library;
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;

namespace Abide_AddOn_API.Controls
{
    /// <summary>
    /// Provides a basic MenuButton Abide AddOn.
    /// </summary>
    [Designer(typeof(Design.MenuButtonDesigner), typeof(IRootDesigner))]
    public class MenuButton : IMenuButton
    {
        private event EventHandler initialize;
        private event EventHandler xboxChanged;
        private event EventHandler indexEntryChanged;
        private event EventHandler disposed;
        private event EventHandler click;
        private event EventHandler nameChanged;
        private event EventHandler descriptionChanged;
        private event EventHandler iconChanged;

        /// <summary>
        /// Occurs when the AddOn's name is changed.
        /// </summary>
        [Browsable(true), Category("Property Changed"), Description("Occurs when the tool's name is changed.")]
        public event EventHandler TextChanged
        {
            add { nameChanged += value; }
            remove { nameChanged -= value; }
        }
        /// <summary>
        /// Occurs when the AddOn's description is changed.
        /// </summary>
        [Browsable(true), Category("Property Changed"), Description("Occurs when the tool's description is changed.")]
        public event EventHandler DescriptionChanged
        {
            add { descriptionChanged += value; }
            remove { descriptionChanged -= value; }
        }
        /// <summary>
        /// Occurs when the AddOn's icon is changed.
        /// </summary>
        [Browsable(true), Category("Property Changed"), Description("Occurs when the tool's icon is changed.")]
        public event EventHandler IconChanged
        {
            add { iconChanged += value; }
            remove { iconChanged -= value; }
        }
        /// <summary>
        /// Occurs when the Debug Xbox is changed
        /// </summary>
        [Browsable(true), Category("API Events"), Description("Occurs when the Debug Xbox is changed")]
        public event EventHandler XboxChanged
        {
            add { xboxChanged += value; }
            remove { xboxChanged -= value; }
        }
        /// <summary>
        /// Occurs when the selected Index Entry is changed
        /// </summary>
        [Browsable(true), Category("API Events"), Description("Occurs when the selected Index Entry is changed")]
        public event EventHandler IndexEntryChanged
        {
            add { indexEntryChanged += value; }
            remove { indexEntryChanged -= value; }
        }
        /// <summary>
        /// Occurs when the Menu Button is clicked
        /// </summary>
        [Browsable(true), Category("Behavior"), Description("Occurs when the Menu Button is clicked")]
        public event EventHandler Click
        {
            add { click += value; }
            remove { click -= value; }
        }
        /// <summary>
        /// Occurs when the AddOn's resources are released.
        /// </summary>
        [Browsable(true), Category("Behavior"), Description("Occurs when the Menu Button's resources are released.")]
        public event EventHandler Disposed
        {
            add { disposed += value; }
            remove { disposed -= value; }
        }
        /// <summary>
        /// The Halo Map version this Abide AddOn is designed to work with
        /// </summary>
        [Browsable(true), Category("AddOn Properties"), Description("The Halo Map version this Abide AddOn is designed to work with")]
        public MapVersion MapVersion
        {
            get { return mapVersion; }
            set { mapVersion = value; }
        }
        /// <summary>
        /// The version of Abide this AddOn is designed to work with
        /// </summary>
        [Browsable(true), Category("AddOn Properties"), Description("The version of Abide this AddOn is designed to work with")]
        public Version AbideVersion
        {
            get { return abideVersion; }
            set { abideVersion = value; }
        }
        /// <summary>
        /// The Author of the Abide AddOn
        /// </summary>
        [Browsable(true), Category("AddOn Properties"), Description("The Author of the Abide AddOn")]
        public string Author
        {
            get { return author; }
            set { author = value; }
        }
        /// <summary>
        /// The version of this Abide AddOn
        /// </summary>
        [Browsable(true), Category("AddOn Properties"), Description("The version of this Abide AddOn")]
        public Version Version
        {
            get { return version; }
            set { version = value; }
        }
        /// <summary>
        /// This Abide AddOn's Description
        /// </summary>
        [Browsable(true), Category("AddOn Properties"), Description("This Abide AddOn's Description")]
        public string Description
        {
            get { return description; }
            set
            {
                bool trigger = description != value;
                description = value;
                if (trigger)
                {
                    descriptionChanged?.Invoke(this, new EventArgs());
                    OnDescriptionChanged(new EventArgs());
                }
            }
        }
        /// <summary>
        /// The Abide AddOn's Display Text
        /// </summary>
        [Browsable(true), Category("Appearance"), Description("The Abide AddOn's Display Text")]
        public string Text
        {
            get { return text; }
            set
            {
                bool trigger = text != value;
                text = value;
                if (trigger)
                {
                    nameChanged?.Invoke(this, new EventArgs());
                    OnTextChanged(new EventArgs());
                }
            }
        }
        /// <summary>
        /// The Abide AddOn's Display Icon
        /// </summary>
        [Browsable(true), Category("Appearance"), Description("The Abide AddOn's Display Icon")]
        public Image Icon
        {
            get { return displayIcon; }
            set
            {
                bool trigger = displayIcon != value;
                displayIcon = value;
                if (trigger)
                {
                    iconChanged?.Invoke(this, new EventArgs());
                    OnIconChanged(new EventArgs());
                }
            }
        }
        /// <summary>
        /// The Abide AddOn Application Programming Interface this Abide AddOn will use
        /// </summary>
        [Browsable(false)]
        public AddOnAPI API
        {
            get { return api; }
        }

        private MapVersion mapVersion = MapVersion.Halo_2;
        private Version abideVersion = AddOnAPI.GetAbideVersion();
        private Version version = new Version(1, 0);
        private string author = "Abide";
        private string text = "MenuButton";
        private string description = string.Empty;
        private string directory = string.Empty;
        private Image displayIcon = null;
        private AddOnAPI api = null;

        protected MenuButton() { }
        protected virtual void OnTextChanged(EventArgs e) { }
        protected virtual void OnDescriptionChanged(EventArgs e) { }
        protected virtual void OnIconChanged(EventArgs e) { }
        protected virtual void OnInitialize(IAddOnHost host)
        {
            //Initialize API
            api = new AddOnAPI(host, this);
        }
        protected virtual void OnXboxChanged(EventArgs e)
        {
            //Throw Event
            if (xboxChanged != null)
                xboxChanged(this, new EventArgs());
        }
        protected virtual void OnIndexEntryChanged(EventArgs e)
        {
            //Throw Event
            if (indexEntryChanged != null)
                indexEntryChanged(this, new EventArgs());
        }
        protected virtual void OnClick(EventArgs e)
        {
            //Throw Event
            if (click != null)
                click(this, e);
        }
        protected virtual void OnDisposed(EventArgs e)
        {
            //Throw Event
            if (disposed != null)
                disposed(this, e);
        }
        protected virtual void OnDispose()
        {
            //Cleanup
            displayIcon.Dispose();
            OnDisposed(new EventArgs());
        }

        event EventHandler IMenuButton.NameChanged
        {
            add { nameChanged += value; }
            remove { nameChanged -= value; }
        }
        event EventHandler IMenuButton.DescriptionChanged
        {
            add { descriptionChanged += value; }
            remove { descriptionChanged -= value; }
        }
        event EventHandler IMenuButton.IconChanged
        {
            add { iconChanged += value; }
            remove { iconChanged -= value; }
        }
        string IMenuButton.Name
        {
            get { return text; }
        }
        string IMenuButton.Description
        {
            get { return description; }
        }
        Image IMenuButton.Icon
        {
            get { return displayIcon; }
        }
        void IMenuButton.Click()
        {
            //Create Args
            var args = new EventArgs();

            //OnClick
            OnClick(args);
        }
        AddOnAPI IAddOn.API
        {
            get { return api; }
        }
        MapVersion IAddOn.MapVersion
        {
            get { return mapVersion; }
        }
        Version IAddOn.Version
        {
            get { return version; }
        }
        Version IAddOn.AbideVersion
        {
            get { return abideVersion; }
        }
        string IAddOn.Author
        {
            get { return author; }
        }
        string IAddOn.Directory
        {
            get { return directory; }
            set { directory = value; }
        }
        void IAddOn.Initialize(IAddOnHost host)
        {
            //Virtual Void
            OnInitialize(host);

            //Throw Event
            if (initialize != null)
                initialize(this, new EventArgs());
        }
        void IAddOn.OnXboxChanged()
        {
            //Virtual Void
            OnXboxChanged(new EventArgs());
        }
        void IAddOn.OnIndexEntryChanged()
        {
            //Virtual Void
            OnIndexEntryChanged(new EventArgs());
        }
        void IDisposable.Dispose()
        {
            //Dispose
            OnDispose();
        }
    }
}
